package com.server.net;

import com.msg.MsgMain;
import com.server.net.message.MsgNotWritableCacheManager;
import com.server.net.message.MsgPack;
import com.server.net.message.MsgProcessorManager;
import com.server.net.session.SessionManager;
import com.server.util.LogUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;

@ChannelHandler.Sharable //使得Handler变成可以共享的(但必须保证线程安全。一般做跨越多个channel的统计信息)
public class NettyProtobufServerHandler extends SimpleChannelInboundHandler<MsgMain.MainProtocl> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, MsgMain.MainProtocl mainProtocl) throws Exception {
        final int msgIndex = mainProtocl.getMessageType().getNumber();
        if (msgIndex % 2 == 0) {
            LogUtil.game.error("CS协议编号必须是奇数:" + msgIndex);
            return;
        }
        Channel channel = channelHandlerContext.channel();
        MsgPack msg = new MsgPack(msgIndex, mainProtocl, channel);
        MsgProcessorManager.getInstance().addMessagePack(msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        MsgNotWritableCacheManager.getInstance().clear(ctx.channel());
        ctx.close();
        LogUtil.game.info("连接异常{}", cause.getMessage());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        Channel channel = ctx.channel();
        MsgNotWritableCacheManager.getInstance().clear(channel);
        SessionManager.getInstance().connect(channel);
        LogUtil.game.info("建立连接" + ctx.channel().remoteAddress() + channel.id().asLongText());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        Channel channel = ctx.channel();
        MsgNotWritableCacheManager.getInstance().clear(channel);
        SessionManager.getInstance().disconnect(channel);
        LogUtil.game.info("连接关闭" + ctx.name());
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        //心跳检测
        if (evt instanceof IdleStateHandler) {
            IdleState state = ((IdleStateEvent) evt).state();
            if (state == IdleState.READER_IDLE) {
                LogUtil.game.info("300秒没收到消息，关闭客户端链接  " + ctx.name());
                Channel channel = ctx.channel();
                MsgNotWritableCacheManager.getInstance().clear(channel);
                channel.close();
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        super.channelWritabilityChanged(ctx);
        //尝试重新发送被isWritable = false拒绝的消息
        MsgNotWritableCacheManager.getInstance().trySendMsgAgain(ctx.channel());
    }
}
